#!/usr/bin/perl
# Client.

use IO::Socket;
use Sys::Hostname;
use threads;
use threads::shared;
use Data::Dumper;
use Time::HiRes qw( usleep ualarm gettimeofday tv_interval nanosleep
clock_gettime clock_getres clock_nanosleep clock
stat );

require "./ia.pl";

my $socket;
my $ia_file = '';
my $port = 0;
my $host = '127.0.0.1';
my $num_args = $#ARGV + 1;
my $adresse = '10.12.180.96';
my @tab_arg = ('-n', '-p', '-h', 'localhost');
my @cmde_time = (7, 7, 7, 7, 1, 7, 7, 7, 7, 300, 42, 0);
my $usage = "\tUsage: ./client -n team -p port [-h hostname]\n";
my @cmde = ('avance', 'droite', 'gauche', 'voir', 'inventaire', 'prend', 'pose', 'expulse', 'broadcast', 'incantation', 'fork', 'connect');

our $nb_send = 0;
our $team = "";
our @in_line : shared = ();
our @transit : shared = ();
our @out_line : shared = ();
our $NO_VAL = "no_val";
our $tmp_send = "";

sub clear_outline()
{
    lock(@out_line);
    @out_line = ();
}

sub clear_all()
{
    lock(@out_line);
    lock(@transit);
    lock(@in_line);
    @out_line = ();
    @transit = ();
    @in_line = ();
}

sub add_outline()
{
    lock(@out_line);
    push(@out_line, $tmp_send);
    $tmp_send = "";
}

sub shift_inline()
{
    lock(@in_line);
    if ($#in_line + 1 > 0) {
	$nb_send--;
	return shift(@in_line);
    }
    return "no_val";
}

sub setter() {
    my $tmp_set = "";
    my @params = @_;
    my $sock = @params[0];

    while (42) {
	if (($#out_line + 1) > 0 && ($#transit + 1) < 9) {
	    {
		lock(@out_line);
		$tmp_set = shift(@out_line);
	    }
	    print "J'envoie $tmp_set \n";
	    print $sock $tmp_set . "\n";
	    {
		lock(@transit);
		push(@transit, $tmp_set);
	    }
	    $nb_send++;
	}
    }
}

sub getter() {
    my $tmp_get = "";
    my @params = @_;
    my $sock = @params[0];

    while (42) {
	$tmp_get = <$sock>;
	if ($tmp_get ne "") {
	    {	
		lock(@in_line);
		push(@in_line, $tmp_get);
	    }
	}
    }
}

sub parseArguments()
{
    if ($num_args != 4 && $num_args != 6 && $num_args != 8) {
	$error = "$num_args : le nombre de parametres est incorrect\n";
    }
    for (my $i = 0; !defined($error) && $i < $num_args; $i++) {
	if ($ARGV[$i] eq "-h" && ($i + 1) < $num_args){
	    $host_tmp = $ARGV[$i + 1];
	    $i++;
	} elsif ($ARGV[$i] eq "-p"){
	    $port = $ARGV[$i + 1];
	    $i++;
	} elsif ($ARGV[$i] eq "-n" && ($i + 1) < $num_args){
	    $team = $ARGV[$i + 1];
	    $i++;
	} elsif ($ARGV[$i] eq "-f" && ($i + 1) < $num_args){
	    $ia_file = $ARGV[$i + 1];
	    $i++;
	}
    }
    if (!defined($error) && ($port == 0)) {
	$error = "Merci de renseigner le port\n";
    } elsif (!defined($error) && $team eq "") {
	$error = "Merci de renseigner le nom de la team\n";
    } 
    if (defined($error)) {
	print "$error $usage";
	exit ;
    }
    if (defined($host_tmp)) {
	$adresse = $host_tmp;
    } else {
	$adresse = $host;
	print "Usage de l'host par default : $host\n";
    }
}

# Creation du socket et connexion.
sub connectSocket()
{
    chomp($adresse);
    print "Tentative de connection au serveur($adresse:$port)\n";
    {
	$socket = IO::Socket::INET->new(PeerAddr => $adresse, Proto => "tcp", PeerPort => $port)
	    or die "Connexion au serveur impossible.\n";
    }
    print "Connexion Etablie!\n";
}

sub createAndExecThreads()
{
    my $th1, $th2;

    $th1 = threads->new(\&setter, $socket);
    $th2 = threads->new(\&getter, $socket);
    $th1->detach;
    $th2->detach;
}

sub runIA()
{
    require "$ia_file";
}

parseArguments();
if ($ia_file eq "") {
    $ia_file = chooseIAFile();
}
connectSocket();
createAndExecThreads();
runIA();
